package com.zxpt.quetion.service.impl;

import com.zxpt.quetion.common.questionType;
import com.zxpt.quetion.pojovo.QuestionItemVo;
import com.zxpt.quetion.pojovo.QuestionOptionsVo;
import com.zxpt.quetion.service.IQuUserQuesService;
import com.zxpt.quetion.service.IQuestionItemService;
import com.zxpt.quetion.service.QuestionCountService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

@Service
@Transactional
@Slf4j
public class QuestionCountServiceImpl implements QuestionCountService {

    @Resource
    private IQuestionItemService questionItemService;
    @Resource
    private IQuUserQuesService userQuesService;

    @Override
    public List<List<Object>> getByMId(String mid,String startTime,String endTime) {
        Map<String, Object> iteam_q_map = new HashMap<>();
        iteam_q_map.put("mid",mid);
        List<QuestionItemVo> base_que_list =questionItemService.getByMIdUid(iteam_q_map);
        base_que_list=base_que_list.stream().filter(x -> !"head".equals(x.getType())).collect(Collectors.toList());
        if(CollectionUtils.isNotEmpty(base_que_list)){
            base_que_list = base_que_list.stream()
                    .sorted(Comparator.comparing(QuestionItemVo::getRealSort)).collect(Collectors.toList());
            base_que_list.forEach(x ->{
                getCount( x, startTime, endTime);
            });
        }
        //得到问题基本信息，选项列表以及每个选项被选中的次数
        final List<List<Object>>[] data = new List[]{new ArrayList<>()};
        base_que_list.forEach( ques_item ->{
            String eng = ques_item.getType();
            String china = questionType.getChina(eng);
            List<Object> ques = Arrays.asList(ques_item.getViewSort()+"."+ques_item.getTitle()+"["+china+"]");
            data[0].add(ques);
            if(CollectionUtils.isNotEmpty(ques_item.getOptions())){
                List<QuestionOptionsVo> op_list = ques_item.getOptions();
                List<Object> text =Arrays.asList("选项","小计","比例");
                data[0].add(text);
                op_list.forEach(op ->{
                    List<Object> op_num =Arrays.asList(op.getLabel(),op.getCountNum(),op.getInRecovery().multiply(new BigDecimal("100"))+"%");
                    data[0].add(op_num);
                    if(CollectionUtils.isNotEmpty(op.getChildren())){
                        List<QuestionOptionsVo> op_list_child = op.getChildren();
                        data[0] = getOpNumText(op_list_child, data[0],1);
                    }
                });
            }else{
                List<Object> text =Arrays.asList("");
                data[0].add(text);
            }
        });
        return data[0];
    }

    //excel文字list
    private List<List<Object>> getOpNumText(List<QuestionOptionsVo> op_list, List<List<Object>> data,int child_lev) {
        String lev ="";
        for(int i=0;i<child_lev;i++){
            lev = lev+"+";
        }
        for(int i =0;i<op_list.size();i++){
            QuestionOptionsVo op = op_list.get(i);
            List<Object> op_num =Arrays.asList(lev+op.getLabel(),op.getCountNum(),op.getInRecovery().multiply(new BigDecimal("100"))+"%");
            data.add(op_num);
            if(CollectionUtils.isNotEmpty(op.getChildren())) {
                child_lev++;
                data = getOpNumText(op.getChildren(), data,child_lev);
            }
        }
        return data;
    }

    //计算回答计数
    private void getCount(QuestionItemVo que,String startTime,String endTime) {
        Map<String, Object> it_u_countMap = new HashMap<>();
        it_u_countMap.put("itemId__equal",que.getId());
        if(!StringUtils.isEmpty(startTime)){
            it_u_countMap.put("cstCreate__get",startTime);
        }
        if(!StringUtils.isEmpty(endTime)){
            it_u_countMap.put("cstCreate__let",endTime);
        }
        Map<String, Integer> getCountMap = userQuesService.getCountValue(it_u_countMap);
        if(!"textarea".equals(que.getType())){
            if("chained".equals(que.getType())){
                getFatherCount( que, getCountMap);
                getRecovery(que.getOptions());
            }else{
                final BigDecimal[] all = {BigDecimal.ZERO};
                que.getOptions().forEach(y ->{
                    if(getCountMap.containsKey(y.getId())){
                        y.setCountNum(getCountMap.get(y.getId()));
                        all[0] = all[0].add(BigDecimal.valueOf(getCountMap.get(y.getId())));
                    }
                });
                que.getOptions().forEach(y ->{
                    if(getCountMap.containsKey(y.getId())){
                        Integer fenzi = y.getCountNum();
                        if(fenzi != 0){
                            BigDecimal fenzi_b = BigDecimal.valueOf(fenzi);
                            BigDecimal re = fenzi_b.divide(all[0], 2, BigDecimal.ROUND_HALF_EVEN);
                            y.setInRecovery(re);
                        }
                    }
                });

            }
        }
    }

    //级联-计算占比
    private List<QuestionOptionsVo> getRecovery(List<QuestionOptionsVo> op_list) {
        AtomicReference<Integer> all = new AtomicReference<>(0);
        op_list.forEach(x ->{
            all.set(all.get() + x.getCountNum());
        });
        BigDecimal all_b =BigDecimal.valueOf(all.get());
        return  getRecovery(op_list,all_b);

    }
    private List<QuestionOptionsVo> getRecovery(List<QuestionOptionsVo> op_list,BigDecimal all) {
        op_list.forEach(y ->{
            Integer fenzi = y.getCountNum();
            if(fenzi != 0){
                BigDecimal fenzi_b = BigDecimal.valueOf(fenzi);
                BigDecimal re = fenzi_b.divide(all, 2, BigDecimal.ROUND_HALF_EVEN);
                y.setInRecovery(re);
                if(CollectionUtils.isNotEmpty(y.getChildren())){
                    getRecovery(y.getChildren(), all);
                }
            }
        });
        return op_list;
    }

    //级联-计算回答计数
    private void getFatherCount(QuestionItemVo que,Map<String, Integer> getCountMap) {
        List<QuestionOptionsVo> father_op_list =que.getOptions();
        List<QuestionOptionsVo> haveLastTreeNum =getLastTreeNum(father_op_list,getCountMap);
        getOtherTreeNum(haveLastTreeNum);
        que.setOptions(haveLastTreeNum);
    }
    //回答过的，最末级（只存了最末级），计数保存
    private List<QuestionOptionsVo> getLastTreeNum(List<QuestionOptionsVo> c_list,Map<String, Integer> getCountMap) {
        c_list.forEach(x ->{
            List<QuestionOptionsVo> cc_list = x.getChildren();
            if(CollectionUtils.isNotEmpty(cc_list)){
                cc_list = this.getLastTreeNum(cc_list,getCountMap);
                x.setChildren(cc_list);
            }else{
                if(getCountMap.containsKey(x.getId())){
                    x.setCountNum(getCountMap.get(x.getId()));
                }
            }
        });
        return c_list;
    }
    //从末级树状向上累加
    private int getOtherTreeNum(List<QuestionOptionsVo> c_list) {
        final int[] treeNodeNum = {0};
        c_list.forEach(x ->{
            int oneNodeNum = 0;
            List<QuestionOptionsVo> cc_list = x.getChildren();
            if(CollectionUtils.isNotEmpty(cc_list)){
                int childrenNnm = getOtherTreeNum(cc_list);
                x.setCountNum( childrenNnm);
                oneNodeNum = oneNodeNum+childrenNnm;
            }else{
                oneNodeNum = x.getCountNum();
            }
            treeNodeNum[0] = treeNodeNum[0]+oneNodeNum;
        });
        return treeNodeNum[0];
    }



}
